x86 numa: Fix SRAT check for discontig memory
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 25 Aug 2009 13:58:42 +0000 (14:58 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 25 Aug 2009 13:58:42 +0000 (14:58 +0100)
We currently compare the sum of the pages found in the SRAT table to
the address of the highest memory page found via the e820 table to
validate the SRAT.  This is completely bogus if there's any kind of
discontiguous memory, where the sum of the pages could be much smaller
than the address of the highest page.  I think all that's necessary is
to validate that each usable memory range in the e820 is covered by an
SRAT entry.  This might not be the most efficient way to do it, but
there are usually a relatively small number of entries on each side.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
xen/arch/x86/srat.c

index 7f90e096857291c06666014d5f65736d69029f49..b49654b78e9f578931d276cbe6cd878066eb6334 100644 (file)
@@ -17,6 +17,7 @@
 #include <xen/nodemask.h>
 #include <xen/acpi.h>
 #include <xen/numa.h>
+#include <asm/e820.h>
 #include <asm/page.h>
 
 static struct acpi_table_slit *acpi_slit;
@@ -236,23 +237,31 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 static int nodes_cover_memory(void)
 {
        int i;
-       u64 pxmram, e820ram;
 
-       pxmram = 0;
-       for_each_node_mask(i, nodes_parsed) {
-               u64 s = nodes[i].start >> PAGE_SHIFT;
-               u64 e = nodes[i].end >> PAGE_SHIFT;
-               pxmram += e - s;
-       }
+       for (i = 0; i < e820.nr_map; i++) {
+               int j, found;
+               unsigned long long start, end;
+
+               if (e820.map[i].type != E820_RAM) {
+                       continue;
+               }
 
-       e820ram = max_page;
-       /* We seem to lose 3 pages somewhere. Allow a bit of slack. */
-       if ((long)(e820ram - pxmram) >= 1*1024*1024) {
-               printk(KERN_ERR "SRAT: PXMs only cover %"PRIu64"MB of your %"
-                       PRIu64"MB e820 RAM. Not used.\n",
-                       (pxmram << PAGE_SHIFT) >> 20,
-                       (e820ram << PAGE_SHIFT) >> 20);
-               return 0;
+               start = e820.map[i].addr;
+               end = e820.map[i].addr + e820.map[i].size - 1;
+
+               found = 0;
+               for_each_node_mask(j, nodes_parsed) {
+                       if (start >= nodes[j].start && end <= nodes[j].end) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       printk(KERN_ERR "SRAT: No PXM for e820 range: "
+                               "%016Lx - %016Lx\n", start, end);
+                       return 0;
+               }
        }
        return 1;
 }